
#include <BLabel>
#include <BGridLayout>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BStyle>
#include <BPainter>

#include "LineStripePanel.h"

BString HexstrFromColor(const BColor& color)
{
	BString text('#');
	char temp[4];
	bByteToHex(temp, color.r());	text << temp;
	bByteToHex(temp, color.g());	text << temp;
	bByteToHex(temp, color.b());	text << temp;
	bByteToHex(temp, color.a());	text << temp;
	return text;
}

LineStripePanel::LineStripePanel(BWidget* parent) : BGroupBox(parent)
{
	this->setTitle("LineStripe");

	BHBoxLayout* buttonLayout = new BHBoxLayout();
	{
		_drawButton = new BButton("draw");
		_drawButton->setCheckable(true);
		_inverseButton = new BButton("inverse");
		buttonLayout->addSpring();
		buttonLayout->addWidget(_drawButton);
		buttonLayout->addWidget(_inverseButton);
	}

	_lineWidthSpinBox = new BFloatSpinBox();
	_lineColorButton = new BButton(Graph_Square_Fill);
	_pointCountSpinBox = new BSpinBox();
	_pointCountSpinBox->setReadOnly(true);

	_lengthSpinBox = new BRealSpinBox();

	BGridLayout* gridLayout = new BGridLayout();
	gridLayout->addWidget(0, 0, new BLabel("line-width"));
	gridLayout->addWidget(0, 1, _lineWidthSpinBox);
	gridLayout->addWidget(1, 0, new BLabel("point-count"));
	gridLayout->addWidget(1, 1, _pointCountSpinBox);
	gridLayout->addWidget(2, 0, new BLabel("line-color"));
	gridLayout->addWidget(2, 1, _lineColorButton);
	gridLayout->addWidget(4, 0, new BLabel("length"));
	gridLayout->addWidget(4, 1, _lengthSpinBox);
	gridLayout->setColumnStretch(0, 0);

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(buttonLayout);
	vlayout->addLayout(gridLayout);

	connect(this, Signal_AssetChanged, &LineStripePanel::slotAssetChanged);
	connect(_drawButton, Signal_Toggled, &LineStripePanel::slotDrawButtonToggled);
	connect(_inverseButton, Signal_Clicked, &LineStripePanel::slotInverseButtonClicked);
	connect(_lineWidthSpinBox, Signal_EditFinished, &LineStripePanel::slotLineWidthEditFinished);
	connect(_lineColorButton, Signal_Clicked, &LineStripePanel::slotLineColorButtonClicked);
	connect(_pointCountSpinBox, Signal_Framed, &LineStripePanel::slotPointCountSpinBoxFramed);

	_drawFilter = new DrawLineStripeFilter;
}
LineStripePanel::~LineStripePanel()
{

}

void LineStripePanel::slotAssetChanged(BObject* object, const BValue& value)
{
	if (LineStripe* stripe = value)
	{
		_lineWidthSpinBox->setValue(stripe->thickness());
		_lineColorButton->setColor(stripe->lineColor());
		const BPointArray& points = stripe->linePoints();
		_pointCountSpinBox->setValue(points.size());
		_lengthSpinBox->setValue(stripe->length());
	}
	else
	{
		_lineWidthSpinBox->setValue(0);
		_lineColorButton->setColor(BColor());
		_pointCountSpinBox->setValue(0);
		_lengthSpinBox->setValue(0);
	}
	_drawFilter->setAsset(value);
}
void LineStripePanel::slotDrawButtonToggled(BObject* object, const BValue& value)
{
	if (value)
	{
		_drawFilter->setAsset(this->asset());
		this->emit("apply-operation", _drawFilter);
	}
	else
	{
		this->emit("remove-operation", _drawFilter);
	}
}
void LineStripePanel::slotInverseButtonClicked(BObject* object, const BValue& value)
{
	if (LineStripe* lineShape = this->asset())
	{
		lineShape->reverse();
		this->emit("show-status", "Inverse successful.");
		this->emit("object-changed", this->asset());
	}
}
void LineStripePanel::slotLineWidthEditFinished(BObject* object, const BValue& value)
{
	if (LineStripe* lineShape = this->asset())
	{
		float thickness = value;
		lineShape->setThickness(thickness);
		this->emit("object-changed", this->asset());
	}
}
void LineStripePanel::slotLineColorButtonClicked(BObject* object, const BValue& value)
{
	if (LineStripe* lineShape = this->asset())
	{
		BColor color = _lineColorButton->color();
		if (_colorDialog.empty())
			_colorDialog = new BColorDialog(this);
		_colorDialog->setColor(color);
		if (_colorDialog->execute())
		{
			color = _colorDialog->color();
			_lineColorButton->setColor(color);
			_lineColorButton->setText(HexstrFromColor(color));
			lineShape->setLineColor(color);
			this->emit("object-changed", this->asset());
		}
	}
}
void LineStripePanel::slotPointCountSpinBoxFramed(BWidget* widget, const BValue& value)
{
	if (LineStripe* stripe = this->asset())
	{
		BPainter painter(widget);
		BRect rect = widget->centerRect();
		rect.left() = rect.right() - rect.height();
		if (stripe->closeLoop())
			painter.drawImage(rect, _loopCloseImage);
		else
			painter.drawImage(rect, _loopOpenImage);
	}
}

void LineStripePanel::styleEvent(const BEvent& event)
{
	BGroupBox::styleEvent(event);
	const BStyle* style = event.value();
	_loopOpenImage = style->image("loop-open");
	_loopCloseImage = style->image("loop-close");
}

void LineStripePanel::showEvent(const BEvent& event)
{
	BGroupBox::showEvent(event);
}
void LineStripePanel::hideEvent(const BEvent& event)
{
	BGroupBox::hideEvent(event);
	this->emit("remove-operation", _drawFilter);
}
